package com.rw.tool.util.basic;

import com.rw.tool.util.collection.CollectionUtil;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 数组工具类
 */
public class ArrayUtil {
    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(byte[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(boolean[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(char[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(short[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(int[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(float[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(long[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 返回数组是否为空
     * 如果为null，则返回false
     *
     * @param array 数组
     * @return 是否为空
     */
    public static boolean isEmpty(double[] array) {
        return array == null || array.length == 0;
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @param <T>   数组类型
     * @return 克隆后的数组
     */
    public static <T> T[] clone(T[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static byte[] clone(byte[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static boolean[] clone(boolean[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static char[] clone(char[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static short[] clone(short[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static int[] clone(int[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static float[] clone(float[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static long[] clone(long[] array) {
        if (array == null) {
            return null;
        }

        return array.clone();
    }

    /**
     * 克隆，把一个数组完全复制一份
     *
     * @param array 数组
     * @return 克隆后的数组
     */
    public static double[] clone(double[] array) {
        if (array == null) {
            return null;
        }
        return array.clone();
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Byte[] boxing(byte[] array) {
        Byte[] boxing = new Byte[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Boolean[] boxing(boolean[] array) {
        Boolean[] boxing = new Boolean[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Character[] boxing(char[] array) {
        Character[] boxing = new Character[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Short[] boxing(short[] array) {
        Short[] boxing = new Short[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Integer[] boxing(int[] array) {
        Integer[] boxing = new Integer[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Float[] boxing(float[] array) {
        Float[] boxing = new Float[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Long[] boxing(long[] array) {
        Long[] boxing = new Long[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 封箱，把基本类型数组变为封装类型的数组
     *
     * @param array 基本类型数组
     * @return 封装类型数组
     */
    public static Double[] boxing(double[] array) {
        Double[] boxing = new Double[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static byte[] Unboxing(Byte[] array) {
        byte[] boxing = new byte[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static boolean[] Unboxing(Boolean[] array) {
        boolean[] boxing = new boolean[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static char[] Unboxing(Character[] array) {
        char[] boxing = new char[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static short[] Unboxing(Short[] array) {
        short[] boxing = new short[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static int[] Unboxing(Integer[] array) {
        int[] boxing = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static float[] Unboxing(Float[] array) {
        float[] boxing = new float[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static long[] Unboxing(Long[] array) {
        long[] boxing = new long[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 拆箱，把封装类型的数组变为基本类型数组
     *
     * @param array 封装类型数组
     * @return 基本类型数组
     */
    public static double[] Unboxing(Double[] array) {
        double[] boxing = new double[array.length];
        for (int i = 0; i < array.length; i++) {
            boxing[i] = array[i];
        }
        return boxing;
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @param <T>   数组的类型
     * @return 被打乱之后的数组
     */
    public static <T> T[] shuffle(T[] array) {
        List<T> list = CollectionUtil.asList(array);
        Collections.shuffle(list);
        return list.toArray(array);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static byte[] shuffle(byte[] array) {
        Byte[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static boolean[] shuffle(boolean[] array) {
        Boolean[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static char[] shuffle(char[] array) {
        Character[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static short[] shuffle(short[] array) {
        Short[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static int[] shuffle(int[] array) {
        Integer[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static float[] shuffle(float[] array) {
        Float[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static long[] shuffle(long[] array) {
        Long[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 打乱数组，并且返回一个新的数组
     *
     * @param array 需要被打乱的数组
     * @return 被打乱之后的数组
     */
    public static double[] shuffle(double[] array) {
        Double[] boxing = boxing(array);
        boxing = shuffle(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @param <T>   数组类型
     * @return 被反转之后的数组
     */
    public static <T> T[] reverse(T[] array) {
        List<T> list = Arrays.asList(array);
        Collections.reverse(list);
        return list.toArray(array);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static byte[] reverse(byte[] array) {
        Byte[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static boolean[] reverse(boolean[] array) {
        Boolean[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static char[] reverse(char[] array) {
        Character[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static short[] reverse(short[] array) {
        Short[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static int[] reverse(int[] array) {
        Integer[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static float[] reverse(float[] array) {
        Float[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static long[] reverse(long[] array) {
        Long[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 反转数组，并返回一个新的数组
     *
     * @param array 需要被反转的数组
     * @return 被反转之后的数组
     */
    public static double[] reverse(double[] array) {
        Double[] boxing = boxing(array);
        boxing = reverse(boxing);
        return Unboxing(boxing);
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @param <T>   被排序数组的类型
     * @return 被排序之后的数组
     */
    public static <T> T[] sort(T[] array) {
        T[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static byte[] sort(byte[] array) {
        byte[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static char[] sort(char[] array) {
        char[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static short[] sort(short[] array) {
        short[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static int[] sort(int[] array) {
        int[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static float[] sort(float[] array) {
        float[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static long[] sort(long[] array) {
        long[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }

    /**
     * 排序数组，并返回一个新的数组
     *
     * @param array 需要被排序的数组
     * @return 被排序之后的数组
     */
    public static double[] sort(double[] array) {
        double[] clone = clone(array);
        Arrays.sort(clone);
        return clone;
    }
}
